package com.tuton.javanet.chapter03;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class ThreadPoolEchoServer {

	private int port = 8000; //server socket's port
	private ServerSocket serverSocket; //server socket
	private Thread02ThreadPool thread02ThreadPool; //thread pool
	private final int POOL_SIZE = 4; //one processor suitable for 4 thread
	
	public ThreadPoolEchoServer() throws IOException {
		serverSocket = new ServerSocket(port);
		//the size of thread pool depend on the number of the center processor
		thread02ThreadPool = new Thread02ThreadPool(
				Runtime.getRuntime().availableProcessors() * POOL_SIZE);
		System.out.println("The ThreadPool Server was started....");
		
	}
	
	public static void main(String[] args) throws IOException {
		new ThreadPoolEchoServer().service();
	}

	private void service() throws IOException {
		Socket socket = null;
		while(true) {
			socket = serverSocket.accept();
			this.thread02ThreadPool.execute(new Handle(socket));
		}
		
	}
	
	private class Handle implements Runnable {

		Socket socket;
		
		public Handle(Socket socket) {
			this.socket = socket;
		}
		
		private BufferedReader getReader(Socket socket) throws IOException {
			InputStream socketIn = socket.getInputStream();
			return new BufferedReader(new InputStreamReader(socketIn));
		}
		
		private PrintWriter getWriter(Socket socket) throws IOException {
			OutputStream socketOut = socket.getOutputStream();
			return new PrintWriter(socketOut,true);
		}
		
		private String echo(String str) {
			return "echo : " + str;
		}
		
		public void run() {
			System.out.println("Accepted a socket from " +
					socket.getInetAddress() + ":" + 
					socket.getPort());
			String msg = null;
			try {
				BufferedReader br = this.getReader(socket);
				PrintWriter    pw = this.getWriter(socket);
				while((msg = br.readLine()) != null) {
					System.out.println(msg);
					pw.println(echo(msg));
					if(msg.equalsIgnoreCase("bye")) {
						break;
					}
				}
			} catch(IOException ex) {
				ex.printStackTrace();
			} finally {
				try{
					if(socket != null) {
						socket.close();
					}
				} catch(IOException ex) {
					ex.printStackTrace();
				}
			}
			
		}
		
	}
	
}
